﻿ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace NeuroProzessorSvc
{
    public partial class svc_Main : ServiceBase
    {
        private TcpServerChannel srv_RM_Neuro_Config;
        private _XML_Cfg _basic_cfg = new _XML_Cfg();

        public svc_Main()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Bei Dienststart
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            IVisual._SC.cls_LOG.LOG_LEVEL = IVisual._SC.cls_LOG.LOGLEVEL.ALL; // Da sonst Fehler nicht zu finden ist!

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "start");
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.INFO, "Dienst wird gestartet");

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Instanziere Prozessor");
            _cls_Controller._Instance = new _cls_NeuroProzessor();

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Instanziere Config");
            _cls_Config _cfg_INIT = new _cls_Config();
            _cfg_INIT.SET_CFG();

            // Lokale Config
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Lade XML-Config");
            string FN = System.IO.Path.GetDirectoryName(System.Environment.GetEnvironmentVariable("appdata")) + "\\RM_Neuro_SVC_config.xml";
            if (System.Security.Principal.WindowsIdentity.GetCurrent().IsSystem)
                FN = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\RM_Neuro_SVC_config.xml";

            if (System.IO.File.Exists(FN))
            {
                try
                {
                    _basic_cfg = (_XML_Cfg)IVisual._SC.cls_Config.Deserialize(FN, typeof(_XML_Cfg));
                    IVisual._SC.cls_LOG.LOG_LEVEL = _basic_cfg.LOGLEVEL;
                    IVisual._SC.cls_LOG.HTML = _basic_cfg.HTML;
                }
                catch(Exception ex)
                {
                    IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.ERROR, ex.Message);
                    IVisual._SC.cls_LOG.LOG_LEVEL = IVisual._SC.cls_LOG.LOGLEVEL.INFO;
                }
            }
            else
                IVisual._SC.cls_LOG.LOG_LEVEL = IVisual._SC.cls_LOG.LOGLEVEL.INFO;

            // AD
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Starte Autodiscovery");
            System.ComponentModel.BackgroundWorker workerAutoDiscovery = new System.ComponentModel.BackgroundWorker();
            workerAutoDiscovery.WorkerReportsProgress = true;
            workerAutoDiscovery.WorkerSupportsCancellation = true;
            IVisual._SC.AutoDiscovery.cls_AutoDiscovery_Server svcAutoDiscovery = new IVisual._SC.AutoDiscovery.cls_AutoDiscovery_Server(ref workerAutoDiscovery, IVisual._SC.cls_tools.LocalIPAddress(), _basic_cfg.NP_Port);
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "AD-IP: " + IVisual._SC.cls_tools.LocalIPAddress() + "AD-Port:" + _basic_cfg.NP_Port);
            workerAutoDiscovery.DoWork += new System.ComponentModel.DoWorkEventHandler(svcAutoDiscovery.Start);
            //workerAutoDiscovery.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(logWorkers_ProgressChanged);
            workerAutoDiscovery.RunWorkerAsync();

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Starte Remote Config-Interface auf Port" + _basic_cfg.NP_Port);
            // Remote-Config
            srv_RM_Neuro_Config = new TcpServerChannel("srv_RM_Neuro_Config", _basic_cfg.NP_Port);
            ChannelServices.RegisterChannel(srv_RM_Neuro_Config, true);
            WellKnownServiceTypeEntry remObj = new WellKnownServiceTypeEntry
            (
                typeof(_cls_Config),
                "_RM_Neuro_Config",
                WellKnownObjectMode.Singleton
            );
            RemotingConfiguration.RegisterWellKnownServiceType(remObj);

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Starte Remote Controller-Interface auf Port" + _basic_cfg.NP_Port);
            //Remote-Controller
            WellKnownServiceTypeEntry remObj1 = new WellKnownServiceTypeEntry
            (
                typeof(_cls_Controller),
                "_RM_Neuro_Controller",
                WellKnownObjectMode.Singleton
            );
            RemotingConfiguration.RegisterWellKnownServiceType(remObj1);

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "ende");
        }

        /// <summary>
        /// Bei Dienst-ende
        /// </summary>
        protected override void OnStop()
        {
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "start");
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.INFO, "Beende Dienst");
            
            // Erzwinge Thread-Ende und warte 0.5sec
            _cls_Controller._Instance._LEARNSTATE = _cls_NeuroProzessor.RUNFLAG.FORCESTOP;
            System.Threading.Thread.Sleep(500);

            // lokale Config
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "Speichere XML-Config");
            try
            {
                string FN = System.IO.Path.GetDirectoryName(System.Environment.GetEnvironmentVariable("appdata")) + "\\RM_Neuro_SVC_config.xml";
                if (System.Security.Principal.WindowsIdentity.GetCurrent().IsSystem)
                    FN = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\RM_Neuro_SVC_config.xml";

                IVisual._SC.cls_Config.Serialize(FN, _basic_cfg);
            }catch(Exception ex)
            {
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.ERROR, ex.Message);
            }

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.INFO, "Dienst beendet");
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "ende");
        }
    }
}
